/**
 * Copyright 2008 Mathias Doenitz, http://lis.to/
 *
 * This file is part of the lis.to java desktop client. The lis.to java desktop client is free software: you can
 * redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * The lis.to java desktop client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with the lis.to java desktop client.
 * If not, see http://www.gnu.org/licenses/
 */

package listo.client.viewlists;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import listo.client.ContextManager;
import listo.client.Convert;
import listo.client.MenuBuilder;
import listo.client.actions.Actions;
import listo.client.dragdrop.FolderViewListTransferHandler;
import listo.client.model.ObjectId;
import listo.client.model.Tasks;
import listo.client.taskfilters.FoldersFilter;
import listo.client.tasklists.TaskList;
import listo.client.tasklists.TaskListManager;
import listo.utils.MiscUtils;
import listo.utils.swing.MouseInterceptor;
import org.apache.commons.lang.ArrayUtils;

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Singleton
public class FolderViewList extends ViewList {

    private final Actions actions;
    private final MenuBuilder menuBuilder;
    private final ContextManager contextManager;
    private final FolderView viewRoot;

    @Inject
    public FolderViewList(ViewListManager viewListManager, ViewListRenderer renderer, FoldersFilter filter,
                          FolderViewListTransferHandler transferHandler, Actions actions, MenuBuilder menuBuilder,
                          ContextManager contextManager, TaskListManager taskListManager, FolderView viewRoot) {
        super(viewListManager, renderer, transferHandler, filter);
        this.actions = actions;
        this.menuBuilder = menuBuilder;
        this.contextManager = contextManager;
        this.viewRoot = viewRoot;

        taskListManager.addTaskSelectionListener(new TaskListManager.TaskSelectionListener() {
            public void taskSelectionChanged(TaskList taskList, Tasks selectedTasks) {
                FolderView.setSelectedTasks(selectedTasks);
                repaint();
            }
        });

        new MouseInterceptor(this) {
            public void mousePressed(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    FolderViewList.this.actions.editFolderAction.actionPerformed(null);
                    e.consume();
                }
                super.mousePressed(e);
            }
        };

        addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                if (getSelectedIndex() != -1) return;
                Component oldFocusOwner = e.getOppositeComponent();
                if (oldFocusOwner instanceof AllTasksViewList) {
                    setSelectedIndex(0);
                } else if (oldFocusOwner instanceof TrashViewList) {
                    setSelectedIndex(getModel().getSize() - 1);
                }
            }
        });

        addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_ENTER:
                        FolderViewList.this.actions.editFolderAction.actionPerformed(null);
                        break;
                    case KeyEvent.VK_DELETE:
                        FolderViewList.this.actions.deleteFoldersAction.actionPerformed(null);
                        break;
                    default:
                        return; // don't consume
                }
                e.consume();
            }
        });
    }

    public FolderView getViewRoot() {
        return viewRoot;
    }

    // called on context change by the incoming filter
    @SuppressWarnings({"unchecked"})
    public void tasksChanged(Object updateObject) {
        Map<ObjectId, Tasks> map = (Map<ObjectId, Tasks>) updateObject;
        FolderView[] oldSelection = Convert.toFolderViews(getSelectedValues());

        List<FolderView> allViews = new ArrayList<FolderView>();
        viewRoot.setFolder(contextManager.getCurrentContext().getRootFolder(), map);
        viewRoot.collectSubTree(allViews);
        allViews.remove(0); // don't show the root view
        setListData(allViews.toArray(new View[allViews.size()]));

        // restore selection state if possible
        if (oldSelection.length > 0) {
            int[] newSelectedIndices = new int[0];
            for (FolderView oldSelectedView : oldSelection) {
                FolderView newSelectedView = findViewForFolderId(oldSelectedView.getFolder().getId());
                if (newSelectedView != null) {
                    newSelectedIndices = ArrayUtils.add(newSelectedIndices, allViews.indexOf(newSelectedView));
                }
            }
            if (newSelectedIndices.length == 0) newSelectedIndices = new int[] {0};
            setSelectedIndices(newSelectedIndices);
        }
    }

    private FolderView findViewForFolderId(ObjectId folderId) {
        for (View folderView : views) {
            if (MiscUtils.equals(((FolderView) folderView).getFolder().getId(), folderId)) {
                return (FolderView) folderView;
            }
        }
        return null;
    }

    protected void createPopupMenu(final MouseEvent e) {
        int clickIndex = locationToIndex(e.getPoint());

        // if the user clicked on a view that is not part of the current selection
        // we select that view before opening the popup menu
        if (!ArrayUtils.contains(getSelectedIndices(), clickIndex)) setSelectedIndex(clickIndex);

        if (!isFocusOwner()) requestFocusInWindow();

        menuBuilder.createPopupMenu(
                actions.addFolderAction,
                actions.editFolderAction,
                actions.deleteFoldersAction,
                null,
                actions.addTaskAction
        ).show(this, e.getX(), e.getY());

        e.consume();
    }

}